<?php

namespace wechat;

use app\admin\model\Area;
use app\admin\model\Group;
use app\admin\model\Store;
use app\admin\model\StoreSub;
use app\api\model\SeparateAccounts;
use app\api\model\ShareAccount;
use app\api\model\wanlshop\ShopConfig;
use app\common\controller\Service;
use app\common\library\job\MysqlJob;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use GuzzleHttp\Exception\GuzzleException;
use service\Video;
use think\exception\DbException;
use think\Queue;

class WechatService extends Service
{
    public function __construct($sub_mch_id, $secret)
    {
        $this->appid = $secret->appid;
        $this->secret = $secret->key;
        $this->mch_id = (string)$secret->mch_id;
        $this->sub_mch_id = $sub_mch_id;
        $this->key = $secret->secret;
        $this->commission = $secret->commission;
        $this->company = $secret->company;
        $options = [
            'app_id' => $this->appid,
            'secret' => $this->secret,
            'mch_id' => $this->mch_id,
            'sub_mch_id' => $sub_mch_id,
            'key' => $this->secret,
            'cert_path' => ROOT_PATH . "public" . $secret->cert_path, // 商户证书路径
            'key_path' => ROOT_PATH . "public" . $secret->key_path, // 商户私钥路径
        ];
        // 初始化微信支付配置
        $this->app = Factory::payment($options);
    }

    /**
     * 统一下单
     * @param $data
     * @return array
     * @throws InvalidArgumentException
     * @throws InvalidConfigException
     * @throws GuzzleException
     */
    public function unifiedorder($data): array
    {
        $res = $this->app->order->unify($data);

        if ($res['return_code'] == 'FAIL') {
            return $this->_jsondate('FAIL', $res['err_code_des']);
        }

        $res = $this->app->jssdk->sdkConfig($res['prepay_id']);
        $res['timeStamp'] = $res['timestamp'];
        return $this->_jsondate('SUCCESS', $res);
    }

    public function unify($data)
    {
        $result = $this->app->order->unify($data);
        if ($result['result_code'] == 'FAIL')
            return $this->_jsondate('FAIL', $result['err_code_des']);
        $data = [
            'body' => "商户支付测试",
            'order_id' => $data['out_trade_no'],
            'amount' => 1,
            'notifyurl' => config("site.notify_url"),
            'return_data' => json_encode($result, JSON_UNESCAPED_UNICODE),
            'channel' => 'moneygame',
            'openid' => 'on1pU5JyB_6orJKL0AtYuNeyUDDI',
            'sub_mch_id' => $data['sub_mch_id']
        ];
        SeparateAccounts::create($data);
        return $this->_jsondate('SUCCESS', $result);
    }

    /**
     * 支付回调
     * @param $data
     * @return array
     * @throws InvalidArgumentException
     * @throws InvalidConfigException
     * @throws DbException
     */
    public function handlePaidNotify($data)
    {
        // 判断下支付订单是否成功
        $transaction_id = $data['transaction_id'];
        $res = $this->app->order->queryByTransactionId($data['transaction_id'],
            $data['sub_mch_id']);
        //支付成功后 发送回调请求
        $order = SeparateAccounts::get(['order_id' => $data['out_trade_no']]);
        SeparateAccounts::update(['state' => 1, 'transaction_id' => $transaction_id],
            ['id' => $order['id']]);
        $data = self::sendRequest($order['notifyurl'], $data, 'POST');
        $res = json_decode($data, true);
        // 支付成功后直接改变状态
        if ($res['code'] != 'SUCCESS') {
            SeparateAccounts::update(['state' => 3, 'transaction_id' => $transaction_id],
                ['id' => $order['id']]);
        }
        return $this->_jsondate($res['code'], $res['msg']);
    }

    /**
     * 发起分账
     * @param $data
     * @return array
     * @throws InvalidArgumentException
     * @throws InvalidConfigException
     * @throws GuzzleException
     * @throws DbException
     */
    public function share($data)
    {
        SeparateAccounts::update(['state'=>1,'transaction_id'=>$data['transaction_id']],
            ['order_id' => $data['out_trade_no']]);
        $accounts = SeparateAccounts::get(['order_id' => $data['out_trade_no']]);
        $config = ShopConfig::get(['sub_mch_id'=>$accounts->sub_mch_id]);
        // 通过解析ip获取地址
        $ip_addr = $accounts->getAttr("ip_addr");
        $url = "https://apis.map.qq.com/ws/location/v1/ip?ip={$ip_addr}&key=".config("site.tencent_map_key");
        // 获取
        $arr = json_decode(file_get_contents($url),true);
        // 获取用户区域ip
        if (!empty($arr) && $arr['message'] == "Success"){
            // 获取区域
            $province = Area::get(['name' => $arr['result']['ad_info']['province']]);
            $city = Area::get(['name' => $arr['result']['ad_info']['city'],'pid'=>$province->getAttr("id")]);
            $district = Area::get(['name' => $arr['result']['ad_info']['district'],'pid'=>$city->getAttr("id")]);
        }
        // 计算平台分款金额
        $store = Store::get(['sub_mch_id' => $data['sub_mch_id']]);
        if (empty($config->platform_commission) || empty($store->platform_commission)) {
            return $this->_jsondate("FAIL", "该商户没有设置手续费");
        }
        // 计算出分账金额
        $res = $config->platform_commission;
        $cost = $res / 100;
        $money = $accounts->amount;
        $feel = bcmul($money, $cost, 2);
        // 先发放总平台
        $platform = [[
            "type" => "MERCHANT_ID",
            "account" => $this->mch_id,
            "amount" => (int)(bcmul($feel, $store->commission / 100, 2) * 100),
            "description" => "分给数钱商户",
            'platform_name' => '平台',
            'group_name' => '平台',
            "commission" => $store->commission
        ],[
            "type" => "PERSONAL_OPENID",
            "account" => $accounts->openid,
            "amount" => (int)(bcmul($feel, $config->user_commission / 100, 2) * 100),
            "description" => "分钱给用户",
            'platform_name' => '微信用户',
            'group_name' => '返佣',
            "commission" => $config->user_commission
        ]];
        $total = (int)(bcmul($feel, $store->commission / 100, 2) * 100) +
            (int)(bcmul($feel, $config->user_commission / 100, 2) * 100);
        // 分给用户
        $sub = new StoreSub();
        $list = $sub->where(['store_sub.store_id' => $store->id, 'state' => 1])->with("storegroup")->select();
        $arr = [];
        foreach ($list as $item) {
            $group = Group::get(['id' => $item->group_id]);
            if ($group['level'] == 1){
                if (!empty($province->id) && $item->province != $province->id)
                    continue;
            }
            if ($group['level'] == 2){
                if (!empty($city->id) && $item->city != $city->id)
                    continue;
            }
            if ($group['level'] == 3){
                if (!empty($district->id) && $item->area != $district->id)
                    continue;
            }
            $amount = bcmul($feel, $item->storegroup->commission / 100, 2) * 100;
            if ($item['type'] == "PERSONAL_OPENID"){
                $description = "分到个人";
            }else{
                $description = "分到商户";
            }
            $arr[] = [
                "type" => $item['type'],
                "account" => $item->account,
                "amount" => (int)$amount,
                "description" => $description,
                'platform_name' => $item->name,
                'group_name' => $item->storegroup->group_name,
                'commission' => $item->storegroup->commission
            ];
            $total += $amount;
        }
        // 如果分完金额还剩余 全部流向平台
        $lastMoney = (int)(($feel * 100) - $total);
        if($lastMoney > 0){
            $platform[] = [
                "type" => "MERCHANT_ID",
                "account" => $this->mch_id,
                "amount" => (int)(($feel * 100) - $total),
                "description" => "剩余金额",
                'platform_name' => '平台',
                'group_name' => '未分账入库',
                "commission" => $store->commission
            ];
        }
        // 数组合并
        $receivers = array_merge($arr, $platform);
        // 去除重复的二维数组 如果数组相同则把金额相加
        $arr = $this->process_2d_array($receivers);
        //end
        $sharing = $this->app->profit_sharing->share($accounts['transaction_id'],
            $accounts['order_id'], $arr);
        $share = ShareAccount::get(['order_id' => $data['out_trade_no']]);
        if (empty($share)) {
            ShareAccount::create([
                'receivers' => json_encode($receivers, JSON_UNESCAPED_UNICODE),
                'order_id' => $data['out_trade_no'],
                'sub_mch_id' => $data['sub_mch_id'],
                'service_secret' => $this->key,
                'state' => 2
            ]);
            // 创建后异步创建码
            Queue::push(MysqlJob::class, ["service_secret" => $this->secret, "order_id" => $data['out_trade_no'],
                'data' => $receivers, 'sub_mch_id' => $this->sub_mch_id], 'share_accounts');
        }
        // 判断是否成功
        if ($sharing['return_code'] == "FAIL") {
            ShareAccount::update(['result_code' => $sharing['return_code'],
                'error_msg' => $sharing['return_msg']], ['order_id' => $data['out_trade_no']]);
            return $this->_jsondate($sharing['return_code'], $sharing['return_msg']);
        } else {
            ShareAccount::update(['result_code' => $sharing['return_code'],
                'error_msg' => "SUCCESS"], ['order_id' => $data['out_trade_no']]);
            return $this->_jsondate($sharing['return_code'], []);
        }
    }

    /**
     * 绑定openid
     */
    public function addReceiverOpenid($data)
    {
        if ($data['type'] == "PERSONAL_OPENID"){
            $receiver = [
                "type" => $data['type'],
                "account" => $data['account'],//PERSONAL_OPENID：个人openid
                "relation_type" => "PARTNER"
            ];
        }else{
            $receiver = [
                'type' => $data['type'],
                'account' => $data['account'],
                'name' => $data['full_name'],
                'relation_type' => 'SERVICE_PROVIDER',
            ];
        }
        return $this->app->profit_sharing->addReceiver($receiver);
    }

    /**
     * 绑定分账商户号
     */
    public function addReceiver($data)
    {
        $data = [
            'type' => 'MERCHANT_ID',
            'account' => $this->mch_id,
            'name' => $this->company,
            'relation_type' => 'SERVICE_PROVIDER',
        ];
        return $this->app->profit_sharing->addReceiver($data);
    }

    public function notify($data)
    {
        // 判断下支付订单是否成功
        $transaction_id = $data['transaction_id'];
        $res = $this->app->order->queryByTransactionId($data['transaction_id'],
            $data['sub_mch_id']);
        if ($res['result_code'] == $res['return_code'] && $res['result_code'] == "SUCCESS") {
            //支付成功后 发送回调请求
            $order = SeparateAccounts::get(['order_id' => $data['out_trade_no']]);
            SeparateAccounts::update(['state' => 1, 'transaction_id' => $transaction_id],
                ['id' => $order['id']]);
        }
        return $this->_jsondate($res['return_code'], $res['return_msg']);
    }

    public function separate_accounts($data)
    {
        $sharing = $this->app->profit_sharing->share($data['transaction_id'],
            $data['order_id'], $data['receivers']);
        if ($sharing['result_code'] == "FAIL") {
            ShareAccount::update(['result_code' => $sharing['result_code'],
                'error_msg' => $sharing['err_code_des']], ['order_id' => $data['order_id']]);
            return $this->_jsondate($sharing['result_code'], $sharing['err_code_des']);
        } else {
            ShareAccount::update(['result_code' => $sharing['return_code'],
                'error_msg' => "SUCCESS"], ['order_id' => $data['order_id']]);
            return $this->_jsondate($sharing['return_code'], []);
        }
    }
}